package com.pointi.test.twittclonetest;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;


import com.pointi.test.twittclonetest.util.http.HttpParameter;
import com.pointi.test.twittclonetest.util.http.ParseBodyHelper;
import com.pointi.test.twittclonetest.util.http.z_T4JInternalStringUtil;
import com.pointi.test.twittclonetest.util.rest.BASE64Encoder;
import com.pointi.test.twittclonetest.util.rest.RestHelper;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.webkit.WebView;
import android.webkit.WebViewClient;

public class TwittCloneTestActivity extends Activity {
	public static final String  LOG_TAG = "TWITT_C";

	public static final String TC_CUSTOMER_KEY		= "eEbmzjGofrXsKUkY96jR7w";
	public static final String TC_CUSTOMER_SECRET 	= "SmM2bUQDMe4m4JgbvnnzSq64ZAanhQIQvlUaZlrM9Tw";

	private static final String HMAC_SHA1 = "HmacSHA1";
	
	public static String REG_CALLBACK = "myapp://twitter";
	
	public static Context mCtx = null;
	
	RestHelper restHelper = new RestHelper();
	


	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		Log.d(LOG_TAG, "FOR DEBUGGING TEST");
		//        HttpClient client = new DefaultHttpClient();
		String url ="https://api.twitter.com/oauth/request_token";
		
		mCtx = this;
		SharedPreferences prefs = getSharedPreferences("OAUTH", MODE_PRIVATE);
		String strOAuthToken = prefs.getString("oauth_token", "");
		String strOAuthTokenSecret = prefs.getString("oauth_token_secret", "");
		
		if(strOAuthToken!= null 
				&& strOAuthToken.length() > 0
				&& strOAuthTokenSecret != null
				&& strOAuthTokenSecret.length() > 0 
				){
			Log.d(LOG_TAG, "ALREADY AUTHORAZED!!![" +strOAuthToken +"]");
			getProfile(strOAuthToken, strOAuthTokenSecret);
			return;
		}
		
		Uri uri = this.getIntent().getData();
		if (uri != null && uri.toString().startsWith(REG_CALLBACK)) {
			
			 return;
//	        String verifier = uri.getQueryParameter("oauth_verifier");
//	        
//	        Log.d(LOG_TAG, "oAuthVerifier:::" + verifier);
	       
		}
		
		WebView wvAuth = (WebView) findViewById(R.id.wv_twitt_clone_auth);
		wvAuth.setWebViewClient(new CustomSchemeWebView());
		
		List<HttpParameter> oauthHeaderParams = new ArrayList<HttpParameter>();
		
//		try {
//			oauthHeaderParams.add(new HttpParameter("oauth_callback", URLEncoder.encode(REG_CALLBACK)));
//		} catch (UnsupportedEncodingException e1) {
//			// TODO Auto-generated catch block
//			e1.printStackTrace();
//		}
		oauthHeaderParams.add(new HttpParameter("oauth_callback", REG_CALLBACK));
        oauthHeaderParams.add(new HttpParameter("oauth_consumer_key", TC_CUSTOMER_KEY));
        oauthHeaderParams.add(new HttpParameter("oauth_signature_method", "HMAC-SHA1"));
        oauthHeaderParams.add(new HttpParameter("oauth_timestamp", ""+(System.currentTimeMillis() / 1000)));
        oauthHeaderParams.add(new HttpParameter("oauth_nonce", "K7ny27JTpKVsTgdyLdDfmQQWVLERj2zAK5BslRsqyw"));
        oauthHeaderParams.add(new HttpParameter("oauth_version", "1.0"));
        
        
//        if (otoken != null) {
//            oauthHeaderParams.add(new HttpParameter("oauth_token", otoken.getToken()));
//        }
        List<HttpParameter> signatureBaseParams = new ArrayList<HttpParameter>(oauthHeaderParams.size());
        signatureBaseParams.addAll(oauthHeaderParams);
//        if (!HttpParameter.containsFile(params)) {
//            signatureBaseParams.addAll(toParamList(params));
//        }
        parseGetParameters(url, signatureBaseParams);
        
        StringBuffer base = new StringBuffer("POST").append("&")
                .append(HttpParameter.encode(constructRequestURL(url))).append("&");
        
        base.append(HttpParameter.encode(normalizeRequestParameters(signatureBaseParams)));
        
        String oauthBaseString = base.toString();
        Log.d(LOG_TAG, "OAuth base string: "+oauthBaseString);
        String signature = generateSignature(oauthBaseString, null);
        Log.d(LOG_TAG, "OAuth signature: "+signature);

        try {
			oauthHeaderParams.add(new HttpParameter("oauth_signature", URLEncoder.encode(signature,"UTF-8")));
		} catch (UnsupportedEncodingException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
        
        ArrayList<NameValuePair> params = new ArrayList<NameValuePair>();
        
        for(HttpParameter param: oauthHeaderParams){
        	NameValuePair addPair = null;
        	if("oauth_callback".equalsIgnoreCase(param.getName())){
//        		try {
					addPair = new BasicNameValuePair(param.getName(),URLEncoder.encode(REG_CALLBACK));
//				} catch (UnsupportedEncodingException e) {
//					// TODO Auto-generated catch block
//					e.printStackTrace();
//				}
        	}
        	else{
        		addPair = new BasicNameValuePair(param.getName(),param.getValue());
        	}
        	
        
        	Log.d(LOG_TAG,"["+addPair.getName()+"][" +addPair.getValue() +"]");
        	params.add(addPair);
        }
        
		String strRtnValue = restHelper.execPost(url, params);
		
		Map mapOAuthBody = ParseBodyHelper.parseAuthBody(strRtnValue);
		
		
		String url2 = "http://api.twitter.com/oauth/authorize?oauth_token=" + mapOAuthBody.get("oauth_token");
		
		Log.d(LOG_TAG, "request URL::::" + url2);
//		String strRtnValue2 = restHelper.execPost(url, params);
		
		wvAuth.loadUrl(url2);

//		Log.d(LOG_TAG, "["+strRtnValue2 +"]");
	}

	/**
	 * @param value string to be encoded
	 * @return encoded string
	 * @see <a href="http://wiki.oauth.net/TestCases">OAuth / TestCases</a>
	 * @see <a href="http://groups.google.com/group/oauth/browse_thread/thread/a8398d0521f4ae3d/9d79b698ab217df2?hl=en&lnk=gst&q=space+encoding#9d79b698ab217df2">Space encoding - OAuth | Google Groups</a>
	 * @see <a href="http://tools.ietf.org/html/rfc3986#section-2.1">RFC 3986 - Uniform Resource Identifier (URI): Generic Syntax - 2.1. Percent-Encoding</a>
	 */
	public static String encode(String value) {
		String encoded = null;
		try {
			encoded = URLEncoder.encode(value, "UTF-8");
		} catch (UnsupportedEncodingException ignore) {
		}
		StringBuffer buf = new StringBuffer(encoded.length());
		char focus;
		for (int i = 0; i < encoded.length(); i++) {
			focus = encoded.charAt(i);
			if (focus == '*') {
				buf.append("%2A");
			} else if (focus == '+') {
				buf.append("%20");
			} else if (focus == '%' && (i + 1) < encoded.length()
					&& encoded.charAt(i + 1) == '7' && encoded.charAt(i + 2) == 'E') {
				buf.append('~');
				i += 2;
			} else {
				buf.append(focus);
			}
		}
		return buf.toString();
	}
	
	private void parseGetParameters(String url, List<HttpParameter> signatureBaseParams) {
        int queryStart = url.indexOf("?");
        if (-1 != queryStart) {
            String[] queryStrs = z_T4JInternalStringUtil.split(url.substring(queryStart + 1), "&");
            try {
                for (String query : queryStrs) {
                    String[] split = z_T4JInternalStringUtil.split(query, "=");
                    if (split.length == 2) {
                        signatureBaseParams.add(
                                new HttpParameter(URLDecoder.decode(split[0],
                                        "UTF-8"), URLDecoder.decode(split[1],
                                        "UTF-8")));
                    } else {
                        signatureBaseParams.add(
                                new HttpParameter(URLDecoder.decode(split[0],
                                        "UTF-8"), ""));
                    }
                }
            } catch (UnsupportedEncodingException ignore) {
            }

        }

    }
	
	/**
     * The Signature Base String includes the request absolute URL, tying the signature to a specific endpoint. The URL used in the Signature Base String MUST include the scheme, authority, and path, and MUST exclude the query and fragment as defined by [RFC3986] section 3.<br>
     * If the absolute request URL is not available to the Service Provider (it is always available to the Consumer), it can be constructed by combining the scheme being used, the HTTP Host header, and the relative HTTP request URL. If the Host header is not available, the Service Provider SHOULD use the host name communicated to the Consumer in the documentation or other means.<br>
     * The Service Provider SHOULD document the form of URL used in the Signature Base String to avoid ambiguity due to URL normalization. Unless specified, URL scheme and authority MUST be lowercase and include the port number; http default port 80 and https default port 443 MUST be excluded.<br>
     * <br>
     * For example, the request:<br>
     * HTTP://Example.com:80/resource?id=123<br>
     * Is included in the Signature Base String as:<br>
     * http://example.com/resource
     *
     * @param url the url to be normalized
     * @return the Signature Base String
     * @see <a href="http://oauth.net/core/1.0#rfc.section.9.1.2">OAuth Core - 9.1.2.  Construct Request URL</a>
     */
    public static String constructRequestURL(String url) {
        int index = url.indexOf("?");
        if (-1 != index) {
            url = url.substring(0, index);
        }
        int slashIndex = url.indexOf("/", 8);
        String baseURL = url.substring(0, slashIndex).toLowerCase();
        int colonIndex = baseURL.indexOf(":", 8);
        if (-1 != colonIndex) {
            // url contains port number
            if (baseURL.startsWith("http://") && baseURL.endsWith(":80")) {
                // http default port 80 MUST be excluded
                baseURL = baseURL.substring(0, colonIndex);
            } else if (baseURL.startsWith("https://") && baseURL.endsWith(":443")) {
                // http default port 443 MUST be excluded
                baseURL = baseURL.substring(0, colonIndex);
            }
        }
        url = baseURL + url.substring(slashIndex);

        return url;
    }
    
    /**
     * Computes RFC 2104-compliant HMAC signature.
     *
     * @param data  the data to be signed
     * @param token the token
     * @return signature
     * @see <a href="http://oauth.net/core/1.0a/#rfc.section.9.2.1">OAuth Core - 9.2.1.  Generating Signature</a>
     */
    /*package*/ String generateSignature(String data, String token_secret) {
        byte[] byteHMAC = null;
        try {
            Mac mac = Mac.getInstance(HMAC_SHA1);
            SecretKeySpec spec = null;
            if (null == token_secret) {
                String oauthSignature = HttpParameter.encode(TC_CUSTOMER_SECRET) + "&";
                spec = new SecretKeySpec(oauthSignature.getBytes(), HMAC_SHA1);
            } else {
//                spec = token.getSecretKeySpec();
                if (null == spec) {
                    String oauthSignature = HttpParameter.encode(TC_CUSTOMER_SECRET) + "&" + HttpParameter.encode(token_secret);
                    spec = new SecretKeySpec(oauthSignature.getBytes(), HMAC_SHA1);
//                    token.setSecretKeySpec(spec);
                }
            }
            mac.init(spec);
            byteHMAC = mac.doFinal(data.getBytes());
        } catch (InvalidKeyException ike) {
            Log.d(LOG_TAG, "Failed initialize \"Message Authentication Code\" (MAC)"+ike);
            throw new AssertionError(ike);
        } catch (NoSuchAlgorithmException nsae) {
            Log.d(LOG_TAG, "Failed to get HmacSHA1 \"Message Authentication Code\" (MAC)"+nsae);
            throw new AssertionError(nsae);
        }
        return BASE64Encoder.encode(byteHMAC);
    }
    
    public static String normalizeRequestParameters(List<HttpParameter> params) {
        Collections.sort(params);
        return encodeParameters(params);
    }
    
    public static String encodeParameters(List<HttpParameter> httpParams) {
        return encodeParameters(httpParams, "&", false);
    }

    public static String encodeParameters(List<HttpParameter> httpParams, String splitter, boolean quot) {
        StringBuffer buf = new StringBuffer();
        for (HttpParameter param : httpParams) {
            if (!param.isFile()) {
                if (buf.length() != 0) {
                    if (quot) {
                        buf.append("\"");
                    }
                    buf.append(splitter);
                }
                buf.append(HttpParameter.encode(param.getName())).append("=");
                if (quot) {
                    buf.append("\"");
                }
                buf.append(HttpParameter.encode(param.getValue()));
            }
        }
        if (buf.length() != 0) {
            if (quot) {
                buf.append("\"");
            }
        }
        return buf.toString();
    }

	@Override
	protected void onNewIntent(Intent intent) {
		// TODO Auto-generated method stub
		Uri uri = intent.getData();
		Log.d(LOG_TAG, "uri" +uri);
		if (uri != null && uri.toString().startsWith(REG_CALLBACK)) {

	        String verifier = uri.getQueryParameter("oauth_verifier");
	        
	        Log.d(LOG_TAG, "oAuthVerifier:::" + verifier);
		}
		super.onNewIntent(intent);
	}
	
	
	
	@Override
	protected void onResume() {
		// TODO Auto-generated method stub
		Uri uri = this.getIntent().getData();
		Log.d(LOG_TAG, "uri::::[" +uri +"]");
		if (uri != null && uri.toString().startsWith(REG_CALLBACK)) {

			String verifier = uri.getQueryParameter("oauth_verifier");
			String token = uri.getQueryParameter("oauth_token");

			Log.d(LOG_TAG, "oAuthVerifier:::" + verifier);
			
			String url = "https://api.twitter.com/oauth/access_token";

			List<HttpParameter> oauthHeaderParams = new ArrayList<HttpParameter>();

			//			try {
			//				oauthHeaderParams.add(new HttpParameter("oauth_callback", URLEncoder.encode(REG_CALLBACK)));
			//			} catch (UnsupportedEncodingException e1) {
			//				// TODO Auto-generated catch block
			//				e1.printStackTrace();
			//			}

			oauthHeaderParams.add(new HttpParameter("oauth_consumer_key", TC_CUSTOMER_KEY));
			oauthHeaderParams.add(new HttpParameter("oauth_signature_method", "HMAC-SHA1"));
			oauthHeaderParams.add(new HttpParameter("oauth_timestamp", ""+(System.currentTimeMillis() / 1000)));
			oauthHeaderParams.add(new HttpParameter("oauth_nonce", "K7ny27JTpKVsTgdyLdDfmQQWVLERj2zAK5BslRsqyw"));
			oauthHeaderParams.add(new HttpParameter("oauth_version", "1.0"));
			oauthHeaderParams.add(new HttpParameter("oauth_verifier", verifier));
			oauthHeaderParams.add(new HttpParameter("oauth_token", token));
			
			List<HttpParameter> signatureBaseParams = new ArrayList<HttpParameter>(oauthHeaderParams.size());
			signatureBaseParams.addAll(oauthHeaderParams);
			//	        if (!HttpParameter.containsFile(params)) {
			//	            signatureBaseParams.addAll(toParamList(params));
			//	        }
			parseGetParameters(url, signatureBaseParams);

			StringBuffer base = new StringBuffer("POST").append("&")
				.append(HttpParameter.encode(constructRequestURL(url))).append("&");

			base.append(HttpParameter.encode(normalizeRequestParameters(signatureBaseParams)));

			String oauthBaseString = base.toString();
			Log.d(LOG_TAG, "OAuth base string: "+oauthBaseString);
			String signature = generateSignature(oauthBaseString, null);
			Log.d(LOG_TAG, "OAuth signature: "+signature);

			try {
				oauthHeaderParams.add(new HttpParameter("oauth_signature", URLEncoder.encode(signature,"UTF-8")));
			} catch (UnsupportedEncodingException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}

			ArrayList<NameValuePair> params = new ArrayList<NameValuePair>();

			for(HttpParameter param: oauthHeaderParams){
				NameValuePair addPair = null;
				if("oauth_callback".equalsIgnoreCase(param.getName())){
					//	        		try {
					addPair = new BasicNameValuePair(param.getName(),URLEncoder.encode(REG_CALLBACK));
					//					} catch (UnsupportedEncodingException e) {
					//						// TODO Auto-generated catch block
					//						e.printStackTrace();
					//					}
				}
				else{
					addPair = new BasicNameValuePair(param.getName(),param.getValue());
				}


				Log.d(LOG_TAG,"["+addPair.getName()+"][" +addPair.getValue() +"]");
				params.add(addPair);
			}

			String strRtnValue = restHelper.execPost(url, params);
			Map mapOAuthBody = ParseBodyHelper.parseAuthBody(strRtnValue);
			
			Log.d(LOG_TAG, "OAUTH_TOKEN==" + mapOAuthBody.get("oauth_token"));
			Log.d(LOG_TAG, "OAUTH_TOKEN_SECRET==" + mapOAuthBody.get("oauth_token_secret"));
			
			SharedPreferences prefs = getSharedPreferences("OAUTH", MODE_PRIVATE);
			SharedPreferences.Editor editor = prefs.edit();
			editor.putString("oauth_token", (String)mapOAuthBody.get("oauth_token"));
			editor.putString("oauth_token_secret", (String)mapOAuthBody.get("oauth_token_secret"));
			editor.commit();
			
			getProfile((String)mapOAuthBody.get("oauth_token"), (String)mapOAuthBody.get("oauth_token_secret"));
			
		}
		super.onResume();
	}


	public void getProfile(String strOAuthToken, String strOAuthSecret){
		String url2 = "https://api.twitter.com/1/account/verify_credentials.json";
		
		List<HttpParameter> oauthHeaderParams2 = new ArrayList<HttpParameter>();
//		oauthHeaderParams2.add(new HttpParameter("oauth_callback", REG_CALLBACK));
		oauthHeaderParams2.add(new HttpParameter("oauth_token",strOAuthToken));
		oauthHeaderParams2.add(new HttpParameter("oauth_consumer_key", TC_CUSTOMER_KEY));
		oauthHeaderParams2.add(new HttpParameter("oauth_signature_method", "HMAC-SHA1"));
		oauthHeaderParams2.add(new HttpParameter("oauth_timestamp", ""+(System.currentTimeMillis() / 1000)));
		oauthHeaderParams2.add(new HttpParameter("oauth_nonce", "K7ny27JTpKVsTgdyLdDfmQQWVLERj2zAK5BslRsqyw"));
		oauthHeaderParams2.add(new HttpParameter("oauth_version", "1.0"));
		
		List<HttpParameter> signatureBaseParams2 = new ArrayList<HttpParameter>(oauthHeaderParams2.size());
		signatureBaseParams2.addAll(oauthHeaderParams2);
		parseGetParameters(url2, signatureBaseParams2);
		

		StringBuffer base2 = new StringBuffer("GET").append("&")
			.append(HttpParameter.encode(constructRequestURL(url2))).append("&");

		base2.append(HttpParameter.encode(normalizeRequestParameters(signatureBaseParams2)));

		String oauthBaseString2 = base2.toString();
		Log.d(LOG_TAG, "OAuth base string: "+oauthBaseString2);
		String signature2 = generateSignature(oauthBaseString2, strOAuthSecret);
		Log.d(LOG_TAG, "OAuth signature: "+signature2);
		
		try {
			oauthHeaderParams2.add(new HttpParameter("oauth_signature", URLEncoder.encode(signature2,"UTF-8")));
		} catch (UnsupportedEncodingException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		
		ArrayList<NameValuePair> params2 = new ArrayList<NameValuePair>();

		for(HttpParameter param: oauthHeaderParams2){
			NameValuePair addPair = null;
			if("oauth_callback".equalsIgnoreCase(param.getName())){
				//	        		try {
				addPair = new BasicNameValuePair(param.getName(),URLEncoder.encode(REG_CALLBACK));
				//					} catch (UnsupportedEncodingException e) {
				//						// TODO Auto-generated catch block
				//						e.printStackTrace();
				//					}
			}
			else{
				addPair = new BasicNameValuePair(param.getName(),param.getValue());
			}


			Log.d(LOG_TAG,"["+addPair.getName()+"][" +addPair.getValue() +"]");
			params2.add(addPair);
			
			
			
		}
		restHelper.execGet(url2, params2);
	}

	private class CustomSchemeWebView extends WebViewClient {
		public boolean shouldOverrideUrlLoading(WebView view, String url) {
			if (url.startsWith("myapp:")) {
				Intent i = new Intent(Intent.ACTION_VIEW);
				i.setData(Uri.parse(url));
				startActivity(i);
				return true;
			}
			return false;
		}
	}


	
    
}